{ "cells": [ { "metadata": {}, "cell_type": "markdown", "source": [ "# Iterable Objects II — Class Notes\n", "\n", "## Try me\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ffraile/computer_science_tutorials/blob/main/source/Introduction/class%20notes/Iterable_Objects_II_Class_Notes.ipynb)[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ffraile/computer_science_tutorials/main?labpath=source%2FIntroduction%2Fclass%20notes%2FIterable_Objects_II_Class_Notes.ipynb)\n", "\n", "These notes summarize the companion notebook [Iterable Objects II](../tutorials/Iterable%20Objects%20II.ipynb) and add **practice cards** and **takeaways** for your exam prep.\n", "\n", "**Key concepts:** Tuples • Dictionaries • Nested Iterables • Comprehensions\n", "**Extra concepts:** Packing/Unpacking (`*`, `**`) • `zip()`\n" ], "id": "de430d1e" }, { "metadata": {}, "cell_type": "markdown", "source": [ "# Introduction\n", "## Motivation\n", " - When we think of programming, we often think of arrays or lists of data.\n", " - However, real-world data is often more complex, and structured.\n", " - In real applications (like the IoT challenge), we need the right data structures to model and manipulate data effectively.\n", "- We need more design choices, data structures built for protection, fast access, or ease of use." ], "id": "ec75d5acf796dbe2" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Objectives\n", "- Pass the basics and understand advanced iterable objects in Python.\n", "- Focus on two foundational data structures: **tuples** and **dictionaries**.\n", "- Specific objectives:\n", " - Pull the key differences between lists, tuples, and dictionaries.\n", " - Understand powerful techniques (nesting, and comprehensions).\n", "- This will give you different design options to manage data in your programs." ], "id": "7b45d8558b56d402" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### Intro for non-programmers\n", "- **Lists** are like arrays: ordered collections of items.\n", "- **Tuples** are like lists, but you can't change them (immutable). Think of them as constants. A layer of protection (prevents unwanted/accidental changes down the line - data integrity). Brings performance wins (pre-allocation - Python knows final size).\n", "- **Dictionaries**: like address books: you look up values by keys (names), not positions. Useful when you need meaningful labels (not just numbers). Easier access to data (closer to how we find info in the real world). Plus, they are also faster than arrays!\n", "- **Nesting**: putting lists/dicts inside each other to model complex data (like a spreadsheet or a matrix).\n", "- **Comprehensions**: concise way to create lists/dicts by transforming/filtering existing ones." ], "id": "8f7c67bc882297e5" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Agenda\n", "**Class overview:**\n", "- Intro & agenda (10 min)\n", "- Recap: Lists (15 min)\n", "- Tuples (10 min)\n", "- Dictionaries (20 min)\n", "- Card break (7 min)\n", "- Nested iterables (15 min)\n", "- Comprehensions (15 min)\n", "- Card break (7 min)\n", "- wrap-up (6 min)\n", "- Homework: Check extra contents and mini-challenges" ], "id": "f5c4a6e217429de1" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## 0) Brief recap: Lists\n", "- **What:** Ordered, indexable, **mutable** sequences.\n", "- Mutable: can change size and content.\n", "- Syntax: `lst = [1, 2, 3]`\n", "- Indexing/Slicing: `lst[i]`, `lst[a:b:c]`\n", "- Useful functions and methods: `len(lst)`, `lst.append(x)`" ], "id": "ec2193458959cf2a" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "row = [\"Peter\", \"Paul\", \"Mary\", \"John\", \"Lucy\"]\n", "# Example 1: head\n", "s = int(input(\"start index: \"))\n", "e = int(input(\"end index: \"))\n", "print(\"Selected names:\", row[s:e])" ], "id": "170f5a188dd17a3" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "# Example 2: rolling update\n", "last_values = [2.3, 2.5, 2.7, 2.9]\n", "i = 0\n", "while True:\n", " new_value = float(input(\"New value (empty to stop): \"))\n", " if not new_value:\n", " break\n", " last_values[i%len(last_values)] = new_value\n", " i += 1\n", " print(\"Rolling average:\", sum(last_values)/len(last_values))" ], "id": "b7840fc9905fa35d" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## 1) Tuples (immutable sequences)\n", "\n", "**What:** Ordered, indexable sequences like lists, but **immutable**.\n", "**Why:** Use for fixed records.\n", "\n", "**Syntax & rules**\n", "- Literal: `t = (1, 2, 3)` (the comma makes the tuple; `(x,)` is a 1‑tuple)\n", "- Indexing/Slicing: Same as lists →`t[i]`, `t[a:b:c]` (read‑only)\n", "- Useful functions and methods: `len(t)`, `t.index(x)`" ], "id": "0512f51f" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "\n", "# Example\n", "unknowns = (\"x\", \"y\", \"z\")\n", "print(\"First:\", unknowns[0])\n", "print(\"Tail:\", unknowns[1:])\n", "try: # This allows us to demonstrate immutability\n", " unknowns[0] = \"X\" # immutability demo\n", "except TypeError as e:\n", " print(\"TypeError:\", e.__class__.__name__)" ], "id": "6d9647d3" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## 2) Dictionaries (mapping values by keys)\n", "\n", "**What:** Key → value store (unordered). Similar to lists, but indexed by **keys** instead of positions.\n", "**Why:** Fast lookups by key; model records, easier to program.\n", "**Create:**\n", "- empty dictionary `d = {}`,\n", "- init with a key value pair`d = {\"k\": 1}`,\n", "**Update**:\n", "- Insert a new value `d[\"l\"] = 2`\n", "**Remove:** `del d[\"k\"]`, `d.pop(\"k\")`\n", "**Lookup:** `\"k\" in d` (by key), `v in d.values()` (by value)\n" ], "id": "7b45d408" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "\n", "contacts = {}\n", "contacts[\"Paco\"] = 655555555\n", "contacts[\"Pepe\"] = 666555111\n", "contacts[\"Pili\"] = 677777555\n", "print(\"All:\", contacts)\n", "\n", "# Literal init\n", "contacts = {\"Paco\": 655555555, \"Pepe\": 666555111, \"Pili\": 677777555}\n", "print(\"Keys:\", list(contacts.keys()))\n", "print(\"Has 'Paco'?\", \"Paco\" in contacts)\n", "print(\"Has number 655... as a VALUE?\", 655555555 in contacts.values())\n", "\n", "# Removal\n", "d = contacts.copy() # d = contacts is a shallow copy! changes will affect both d and contacts\n", "del d[\"Pepe\"] # Remove\n", "pili = d.pop(\"Pili\") # Retrieve & remove. Nice if you need the value.\n", "print(\"After removals:\", d)\n", "\n" ], "id": "61768f5f" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### 2.1) Iteration patterns\n", "- `in` tests membership on **keys**: `\"k\" in d` `True` if key exists.\n", "- Keys (default): `for k in d:` or `for k in d.keys():`\n", "- Values: `for v in d.values():`\n", "- Pairs: `for k, v in d.items():`" ], "id": "808b47a557c538b3" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "# Iteration\n", "for name in contacts:\n", " print(\"Key only:\", name, \"→\", contacts[name])\n", "\n", "for name, phone in contacts.items():\n", " print(\"Pair:\", name, phone)" ], "id": "69cba018e3427a1" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### 2.2) Safe read:\n", "- `d[key]` raises `KeyError` if key missing.\n", "- Method `d.get(key)` returns `None` if key missing.\n", "- Use `d.get(key, default)` to avoid `KeyError` if key missing." ], "id": "d39e160343c055e0" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "d = {\"a\": 1, \"b\": 2}\n", "print(\"d['a']:\", d[\"a\"])\n", "print(\"d.get('a'):\", d.get(\"a\"))\n", "print(\"d.get('c'):\", d.get(\"c\")) # missing key\n", "print(\"d.get('c', 42):\", d.get(\"c\", 42)) # missing key with default" ], "id": "338e487939f8ba3" }, { "cell_type": "markdown", "id": "72e111d4", "metadata": {}, "source": [ "# Exercise Cards (Peer Instruction)\n", "\n", "**How to use:** predict → discuss → run the check cell (where provided). Keep answers short (*what + why*)." ] }, { "cell_type": "markdown", "id": "8c17cbb2", "metadata": {}, "source": [ "### Card 1 — Tuple immutability (predict result)\n", "```python\n", "t = (\"A\", \"B\", \"C\")\n", "t[0] = \"Z\"\n", "```\n", "**Q:** Does this run without exceptions? If not, what is the error?" ] }, { "cell_type": "markdown", "id": "a36bb11c", "metadata": {}, "source": [ "### Card 2 — Keys vs values (predict the result)\n", "Given:\n", "```python\n", "contacts = {\"Paco\": 655555555, \"Pepe\": 666555111}\n", "```\n", "**Q:** Which is `True`? Choose all that apply. \n", "`\"Paco\" in contacts` • `655555555 in contacts` • `655555555 in contacts.values()`" ] }, { "cell_type": "code", "execution_count": null, "id": "f59c8920", "metadata": {}, "outputs": [], "source": [ "\n", "contacts = {\"Paco\": 655555555, \"Pepe\": 666555111}\n", "print(\"A:\", \"Paco\" in contacts)\n", "print(\"B:\", 655555555 in contacts)\n", "print(\"C:\", 655555555 in contacts.values())" ] }, { "cell_type": "markdown", "id": "bedf61a1", "metadata": {}, "source": [ "### Card 3 — Items iteration (predict printed pairs)\n", "```python\n", "d = {\"x\":1, \"y\":2}\n", "for k, v in d.items():\n", " print(f\"square of {k} is {v**2}\")\n", "```\n", "**Q:** What is printed?" ] }, { "cell_type": "code", "id": "3af9447a", "metadata": { "ExecuteTime": { "end_time": "2025-11-18T08:24:03.261595Z", "start_time": "2025-11-18T08:24:03.258871Z" } }, "source": [ "\n", "d = {\"x\":1, \"y\":2}\n", "for k, v in d.items():\n", " print(f\"square of {k} is {v**2}\")" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "square of x is 1\n", "square of y is 4\n" ] } ], "execution_count": 1 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## 3) Nested iterables\n", "\n", "- **List of lists** (matrix‑like): `[[1,2],[3,4]]`\n", "- **List of dicts** (records): `[{\"name\":\"Pepe\",\"age\":19}, ...]`\n", "- **Dicts with list values**: `{\"colors\": [\"Orange\",\"Blue\"]}`\n", "\n", "**Indexing through levels:** `data[1][\"name\"]`, `matrix[0][0]`" ], "id": "6f4c2765" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "\n", "# List of lists\n", "grid = [[1, 2],\n", " [3, 4]]\n", "print(\"grid[0] ->\", grid[0])\n", "print(\"grid[0][0] ->\", grid[0][0])\n", "\n", "# List of dicts\n", "students = [{\"name\": \"Pepe\", \"age\": 19},\n", " {\"name\": \"Ingrid\", \"age\": 18}]\n", "print(\"Second student's name:\", students[1][\"name\"])\n", "\n", "\n" ], "id": "e4a8a356" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "## Mini challenge\n", "# Print the age of student Ingrid\n" ], "id": "7648e2b2d25205e2" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "# Mini challenge\n", "## For each of the two nested lists below, find the value 1 using indexing and print it\n", "# Mini challenges\n", "a = [[0, 0], [1,0]]\n", "b = [[[0, 0], [0, 0]], [[1, 0], [0, 0]]]\n" ], "id": "d730e4b3b91d9faa" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### 3.1) Iteration over nested structures\n", "- Access specific fields during iteration:\n", "```python\n", "for student in students:\n", " print(student[\"name\"])\n", "```\n", "- Iterate outer, then inner:\n", "```python\n", "records = [{\"name\":\"A\",\"age\":19},{\"name\":\"B\",\"age\":18}]\n", "for record in records:\n", " for key, value in record.items():\n", " ...\n", "```\n" ], "id": "7ecd19dc9b3d4239" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "records = [{\"name\":\"A\",\"age\":19},{\"name\":\"B\",\"age\":18}]\n", "for record in records:\n", " print(record[\"name\"])\n", "\n", "for record in records:\n", " for key, value in record.items():\n", " print(f\"{key}: {value}\")\n" ], "id": "92aa57b436b3c85c" }, { "metadata": {}, "cell_type": "code", "source": [ "# Mini challenge:\n", "## Use a for loop to find the average temperature\n", "\n", "arduino_log = [{\"time\": \"2022 - 08 - 31 00: 15\", \"temp\": 25.6, \"humidity\": 66},\n", " {\"time\": \"2022 - 08 - 31 00: 45\", \"temp\": 25.9, \"humidity\": 67},\n", " {\"time\": \"2022 - 08 - 32 00: 00\", \"temp\": 25.7, \"humidity\": 66},\n", " {\"time\": \"2022 - 08 - 32 00: 15\", \"temp\": 25.6, \"humidity\": 65}]\n" ], "id": "7f67beed1bd04781", "outputs": [], "execution_count": null }, { "metadata": {}, "cell_type": "markdown", "source": [ "## 4) Comprehensions\n", "\n", "**List comp**: `[expr for x in xs if cond]`\n", "**Dict comp**: `{key_expr: val_expr for ...}`\n", "\n", "**Good for:** small, readable transformations/filters. Prefer loops for complex logic." ], "id": "46a88cb2" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "\n", "keys = ('a', 'b', 'c', 'd')\n", "values = (1, 2, 3, 4)\n", "\n", "squares = [i*i for i in values]\n", "even_squares = [i*i for i in values if i % 2 == 0]\n", "new_dict = {keys[i]: squares[i] for i in range(len(keys))}\n", "\n", "print(\"squares:\", squares)\n", "print(\"even_squares:\", even_squares)\n", "print(\"new_dict:\", new_dict)" ], "id": "6482b0f9" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "# Tiny \"average grade\" demo without input()\n", "samples = [{\"name\":\"A\", \"grade\": 7.5},\n", " {\"name\":\"B\", \"grade\": 9.0},\n", " {\"name\":\"C\", \"grade\": 6.5}]\n", "avg = sum(s[\"grade\"] for s in samples)/len(samples)\n", "print(\"Average grade:\", round(avg, 2))" ], "id": "62ad91ccc4a60732" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "# Mini challenge\n", "# Use comprehension to find the average humidity\n", "arduino_log = [{\"time\": \"2022 - 08 - 31 00: 15\", \"temp\": 25.6, \"humidity\": 66},\n", " {\"time\": \"2022 - 08 - 31 00: 45\", \"temp\": 25.9, \"humidity\": 67},\n", " {\"time\": \"2022 - 08 - 32 00: 00\", \"temp\": 25.7, \"humidity\": 66},\n", " {\"time\": \"2022 - 08 - 32 00: 15\", \"temp\": 25.6, \"humidity\": 65}]\n" ], "id": "ae504002612c80ae" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### 4.2) Common patterns\n", "- **Extract field list:** `[r[\"name\"] for r in records]`\n", "- **Filter records:** `[r for r in records if r[\"age\"] >= 18]`\n", "- **Build dict from list:** `{r[\"name\"]: r[\"age\"] for r in records}`\n", "- **Aggregate:** `sum(r[\"age\"] for r in records) / len(records)`\n" ], "id": "a3708dde2f2f941f" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "records = [{\"name\":\"Samantha Eve\",\"age\":19},{\"name\":\"Mark Grayson\",\"age\":18},{\"name\":\"Amber Bennet\",\"age\":17}]\n", "# Minichallenge: Discuss in peers and understand the following comprehensions\n", "names = [r[\"name\"] for r in records]\n", "adults = [r for r in records if r[\"age\"] >= 18]\n", "age_dict = {r[\"name\"]: r[\"age\"] for r in records}\n", "avg_age = sum(r[\"age\"] for r in records) / len(records)\n", "print(\"Names:\", names)\n", "print(\"Adults:\", adults)\n", "print(\"Age dict:\", age_dict)\n", "print(\"Average age:\", avg_age)" ], "id": "9d5bfc6a15121026" }, { "metadata": {}, "cell_type": "markdown", "source": [ "# Exercise Cards (Peer Instruction)\n", "\n", "**How to use:** predict → discuss → run the check cell (where provided). Keep answers short (*what + why*)." ], "id": "5d2a23767dc5b237" }, { "cell_type": "markdown", "id": "bc4cfedb", "metadata": {}, "source": [ "### Card 4 — Nested access\n", "```python\n", "students = [{\"name\":\"A\",\"age\":19},{\"name\":\"B\",\"age\":18}]\n", "```\n", "**Q:** Predict: `students[1][\"age\"]` and `students[0][\"name\"]`." ] }, { "cell_type": "code", "execution_count": null, "id": "9289219b", "metadata": {}, "outputs": [], "source": [ "\n", "students = [{\"name\":\"A\",\"age\":19},{\"name\":\"B\",\"age\":18}]\n", "print(students[1][\"age\"], students[0][\"name\"])" ] }, { "cell_type": "markdown", "id": "fe6466d3", "metadata": {}, "source": [ "### Card 5 — Comprehension with condition\n", "```python\n", "vals = [0,1,2,3,4]\n", "out = [v*v for v in vals if v%2==0]\n", "```\n", "**Q:** What is `out`?" ] }, { "cell_type": "code", "execution_count": null, "id": "c858ea62", "metadata": {}, "outputs": [], "source": [ "\n", "vals = [0,1,2,3,4]\n", "out = [v*v for v in vals if v%2==0]\n", "print(out)" ] }, { "cell_type": "markdown", "id": "f597b066", "metadata": {}, "source": [ "### Card 6 — Dict comprehension\n", "Map letters to their squared index (0-based) for `\"abcd\"`:\n", "```python\n", "letters = \"abcd\"\n", "# result should be: {'a':0, 'b':1, 'c':4, 'd':9}\n", "```\n", "**Q:** Predict or sketch the comp; then run the check." ] }, { "cell_type": "code", "execution_count": null, "id": "8ac507af", "metadata": {}, "outputs": [], "source": [ "\n", "letters = \"abcd\"\n", "res = {ch: i*i for i, ch in enumerate(letters)}\n", "print(res)" ] }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Extra (Not covered in exam)\n", "### 5) Packing & Unpacking (`*`, `**`)\n", "\n", "- **Tuple unpack:** `a, b = (1, 2)`; extended: `first, *mid, last = t`\n", "- **Call-time unpack:** `f(*args_tuple)`; keyword unpack: `g(**kwargs_dict)`\n", "- Useful with functions like `range`, `print`." ], "id": "f9d2ceaa" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "\n", "t = (1, 2, 3, 4)\n", "a, b, c, d = t\n", "print(a, b, c, d)\n", "\n", "first, *g, last = t\n", "print(\"first:\", first, \"| g:\", g, \"| last:\", last)\n", "\n", "# Call-time unpack\n", "range_args = (1, 10, 3)\n", "print(\"range(*range_args):\", list(range(*range_args)))\n", "\n", "args = (\"first string\", \"second string\")\n", "key_args = {\"sep\": \", \", \"end\": \"\\n\"}\n", "print(*args, **key_args)" ], "id": "51b9e98b" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### 6) `zip()`\n", "\n", "**What:** Combine iterables position-wise into tuples.\n", "**Stops** at the shortest input.\n", "**Unzip:** `a, b = zip(*pairs)` (works if not empty)." ], "id": "6604621e" }, { "metadata": { "ExecuteTime": { "end_time": "2025-10-27T10:20:48.348709Z", "start_time": "2025-10-27T10:20:48.346260Z" } }, "cell_type": "code", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "pairs: [(1, 4), (2, 5), (3, 6)]\n", "pairs_dict: {'a': 1, 'b': 2, 'c': 3}\n", "unzipped a: (1, 2, 3) | b: (4, 5, 6)\n" ] } ], "execution_count": 5, "source": [ "\n", "x = (1, 2, 3)\n", "y = (4, 5, 6, 7)\n", "k = (\"a\", \"b\", \"c\")\n", "pairs = list(zip(x, y))\n", "pairs_dict = dict(zip(k, x)) # k: x mapping nice pattern for dicts\n", "print(\"pairs:\", pairs)\n", "print(\"pairs_dict:\", pairs_dict)\n", "\n", "# Unzip (guard empty)\n", "if pairs:\n", " a, b = zip(*pairs)\n", " print(\"unzipped a:\", a, \"| b:\", b)" ], "id": "25308bbc" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Extra Cards\n", "### Card 7 — Nested iterables\n", "What is the output of:\n", "```python\n", "data = {\"colors\": [\"Red\", \"Green\", \"Blue\"], \"numbers\": [1, 2, 3]}\n", "print(data[\"colors\"][1])\n", "```\n", "\n" ], "id": "12821b1d6b489b2a" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "data = {\"colors\": [\"Red\", \"Green\", \"Blue\"], \"numbers\": [1, 2, 3]}\n", "print(data[\"colors\"][1])" ], "id": "90ae6ebc4e5ad537" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### Card 8 - Comprehension vs loop\n", "Which of these snippets produces the same result?\n", "```python\n", "# Snippet A\n", "result_A = []\n", "for i in range(5):\n", " if i % 2 == 0:\n", " result_A.append(i * i)\n", "# Snippet B\n", "result_B = [i * i for i in range(5)]\n", "# Snippet C\n", "result_C = [i * i for i in range(5) if i % 2 == 0]\n", "# Snippet D\n", "result_D = sum([i * i for i in range(5) if i % 2 == 0])\n", "\n", "```" ], "id": "b90bd75c017dcddf" }, { "metadata": { "ExecuteTime": { "end_time": "2025-10-27T10:35:46.094621Z", "start_time": "2025-10-27T10:35:46.091934Z" } }, "cell_type": "code", "source": [ "# Snippet A\n", "result_A = []\n", "for i in range(5):\n", " if i % 2 == 0:\n", " result_A.append(i * i)\n", "# Snippet B\n", "result_B = [i * i for i in range(5)]\n", "# Snippet C\n", "result_C = [i * i for i in range(5) if i % 2 == 0]\n", "# Snippet D\n", "result_D = sum([i * i for i in range(5) if i % 2 == 0])\n", "\n", "print(f\"result_A: {result_A}\")\n", "print(f\"result_B: {result_B}\")\n", "print(f\"result_C: {result_C}\")\n", "print(f\"result_D: {result_D}\")\n" ], "id": "769b892e33832e3c", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "result_A: [0, 4, 16]\n", "result_B: [0, 1, 4, 9, 16]\n", "result_C: [0, 4, 16]\n", "result_D: 20\n" ] } ], "execution_count": 7 }, { "metadata": {}, "cell_type": "markdown", "source": [ "### Card 9 — Scalar product with comprehension\n", "What is the output of:\n", "```python\n", "a = [1, 2, 3]\n", "b = [4, 5, 6]\n", "c = sum(a[i] * b[i] for i in range(len(a)))\n", "```" ], "id": "563a39669062ed5c" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ "a = [1, 2, 3]\n", "b = [4, 5, 6]\n", "c = sum(a[i] * b[i] for i in range(len(a)))" ], "id": "fc6fb1e1fb6351d1" }, { "metadata": {}, "cell_type": "markdown", "source": [ "### Card 10 - Series with comprehension\n", "Which of these snippets produces a geometric series with common ratio of $\\frac{1}{2}$, that is ($\\frac{1}{2} + \\frac{1}{4} + \\frac{1}{8} + ...$ up to `n`?\n", "```python\n", "n = 5\n", "# Snippet A\n", "s_A = sum(1 /2 for i in range(n))\n", "# Snippet B\n", "s_B = sum(1 / (2 ** i) for i in range(1, n + 1))\n", "# Snippet C\n", "s_C = sum(1 / (2 ** i) for i in range(n))\n", "\n" ], "id": "dc7e3ee6db83a4f4" }, { "metadata": { "ExecuteTime": { "end_time": "2025-10-27T10:46:45.441587Z", "start_time": "2025-10-27T10:46:45.439187Z" } }, "cell_type": "code", "source": [ "n = 5\n", "# Snippet A\n", "s_A = sum(1 /2 for i in range(n))\n", "# Snippet B\n", "s_B = sum(1 / (2 ** i) for i in range(1, n + 1))\n", "# Snippet C\n", "s_C = sum(1 / (2 ** i) for i in range(n))\n", "\n", "print(f\"s_A: {s_A}\")\n", "print(f\"s_B: {s_B}\")\n", "print(f\"s_C: {s_C}\")" ], "id": "b2bd7c75129bdc5e", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s_A: 2.5\n", "s_B: 0.96875\n", "s_C: 1.9375\n" ] } ], "execution_count": 8 }, { "cell_type": "markdown", "id": "ac498457", "metadata": {}, "source": [ "## Mini Challenges (apply patterns)\n", "\n", "1) **Filter + transform:** From `students` (list of dicts with `grade`), build a list of names of students with `grade >= 8`, uppercased. *(One line comprehension or a tiny loop.)*\n" ] }, { "cell_type": "code", "execution_count": null, "id": "7382d99f", "metadata": {}, "outputs": [], "source": [ "\n", "\n" ] }, { "metadata": {}, "cell_type": "markdown", "source": "2) **Dict from pairs:** Given `keys = [\"id\",\"name\",\"age\"]` and `row = [101,\"Ada\",28]`, build `{\"id\":101,\"name\":\"Ada\",\"age\":28}` using `zip`.\n", "id": "d057e42afbb54383" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": "\n", "id": "23cd5127e25f25a" }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Takeaways\n", "- **Tuples** are immutable: safe to share, great for fixed records and unpacking.\n", "- **Dictionaries** store by **key**; test membership on keys (`k in d`) or on values (`v in d.values()`).\n", "- **Nested data** is just layers: index your way down (`data[1][\"x\"][0]`).\n", "- **Comprehensions** are ideal for small, clear transformations; prefer loops if it gets dense.\n", "- `*` and `**` unpack positional/keyword arguments—handy with `range`, `print`, and functions you write.\n", "- **`zip`** combines; `zip(*pairs)` unzips; stops at the shortest input.\n", "- Aim for **minimal changes** to fix intent (great exam habit)." ], "id": "1308174e" } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.x" } }, "nbformat": 4, "nbformat_minor": 5 }